#include "StdAfx.h"
#include "../sgp/Rect.h"
#include "../sgp/VideoSurfaceLock.h"
#include "..\sgp\ImageDataIndexed.h"

namespace ja2{ namespace sgp
{
	ImageDataIndexed::ImageDataIndexed(std::uint16_t Size, PaletteVector_t &&Palette)
		: m_Palette(std::forward<PaletteVector_t>(Palette))
	{
		// Reserve size
		m_SubImages.reserve(Size);
	}

	void ImageDataIndexed::blit_transparent(IDirectDrawSurfacePtr &pSurface, Rect const &SourceRect) const
	{
		static std::uint8_t const STCI_TRANSPARENT = 0x80;
		static std::uint8_t const STCI_RUN_LIMIT = 0x7F;

		auto const bit_depth = 32 / 8;
		// Get sub-image (left coordinate is index)
		auto const &tuple = m_SubImages.at(SourceRect.left());
		// Lock surface
		VideoSurfaceLock lock(pSurface);
		char *p_src_line = std::get<0>(tuple).get();
		// Blit data
		for(std::uint_least32_t i = 0; i < std::get<1>(tuple).height(); ++i)
		{
			// Get the dest line
			char *p_dest_line = static_cast<char *>(lock.buffer()) + i * lock.pitch();
			for(std::uint_least32_t j = 0; j < std::get<1>(tuple).width(); )
			{
				// Transparent pixels
				if(static_cast<unsigned char>(*p_src_line) & STCI_TRANSPARENT)
				{
					// Get number of pixel
					std::uint_least8_t const no_pixels = static_cast<unsigned char>(*(p_src_line++)) & STCI_RUN_LIMIT;
					std::uint_least8_t const no_pixels_byte = no_pixels * bit_depth;
					// Set pixels and move forward
					std::fill(p_dest_line, p_dest_line + no_pixels_byte, 0);
					p_dest_line += no_pixels_byte;
					j += no_pixels;
				}
				// Non-transparent pixels
				else
				{
					std::uint_least8_t const no_pixels = *(p_src_line++);
					// Set pixel data
					for(auto k = 0; k != no_pixels ; k++)
					{
						std::uint_least8_t const pixel_index = *(p_src_line++);
						// If shadow, set as transparent
						if(pixel_index == 254)
						{
							std::fill(p_dest_line, p_dest_line + bit_depth, 0);
							p_dest_line += bit_depth;
						}
						// Palette
						else
						{
							// Get palette entry
							auto const &pal_entry = m_Palette.at(pixel_index);
							// Set color
							*(p_dest_line++) = pal_entry.Red;
							*(p_dest_line++) = pal_entry.Green;
							*(p_dest_line++) = pal_entry.Blue;
							*(p_dest_line++) = 0;
						}
					}
					j += no_pixels;
				}
				// New line
				if(*p_src_line == 0)
					++p_src_line;
			}
		}
	}
	
	void ImageDataIndexed::blit_shadow(IDirectDrawSurfacePtr &/*pSurface*/, Rect const &/*SourceRect*/) const
	{
		JA2_ASSERT_MESAGE(false, "Not implemented");
	}

	void ImageDataIndexed::add_sub_image(DataType_t &&pData, Rect const &SourceRect)
	{
		m_SubImages.push_back(DataPair_t(std::forward<DataType_t>(pData), SourceRect));
	}

	PaletteVector_t const *ImageDataIndexed::palette() const
	{
		return &m_Palette;
	}
} /*sgp*/} /*ja2*/